///////////////////////////////////////////////////////////////////
// Student name:Jon Hersack and Caleb Reinking
// Course: COSC 3403
// Assignment: #7 - Initial Software Construction
// File name:Controller.java
// Purpose: Provides logic checking for game functions and manages the
// gameplay progression
// Assumptions:none known
// Limitations:none known
// Development Computer:Intel core2 duo 2.67Ghz
// Operating System: windows
// Integrated Development Environment (IDE): netbeans 6.5
// Compiler: Javac java 1.6.0_13
///////////////////////////////////////////////////////////////////
import java.util.*;

public class Controller
{
    Vector<Team> teamVect;
    Deck mainDeck;//will be singleton
    ScoreKeeper handScorer;
    int activeTeam;
    UserInterface myUserInterface;
    Scanner console = console = new Scanner(System.in);
    String Names[][] = new String[2][3];

    //contructors
    Controller()
    {
        Names[0][0] = "Team 1";
        Names[1][0] = "Team 2";
        Names[0][1] = "Player 1";
        Names[0][2] = "Player 2";
        Names[1][1] = "Player 3";
        Names[1][2] = "Player 4";
        myUserInterface = new UserInterface();
        myUserInterface.printMainSplash();
        console.nextLine();//wait for enter press
        

        teamVect = new Vector<Team>(2);

        
        Names = myUserInterface.getNames();

        int gameType = myUserInterface.getGameType();
       if(gameType == 3)
        {
            teamVect.add(new Team(1, Names[0], 0));//team 1,1 human player
        }//end if human game
       else
       {
            teamVect.add(new Team(0, Names[0], 0));//team 1,2 computer players
       }

        teamVect.add(new Team(0,  Names[1], 1));//team 2,2 computer players

        mainDeck = Deck.getInstanceOf();
        handScorer = ScoreKeeper.getInstanceOf();
        activeTeam = 0;
    }//blank contructor

    public Team getTeam(int teamIndex)
    {
        return teamVect.elementAt(teamIndex);
    }

    public Team getActiveTeam()
    {
        return teamVect.elementAt(activeTeam);
    }

    //#####################################################
    void deal()
    {

    }//end method deal

    //#####################################################
    void newHand()
    {

    }//end method newhand

    //#####################################################
    void startGame()
    {        
        
        dealToTeams();
        

        while(!gameOver())
        {
            while(!handOver())
            {
                startTurn();
            }
            teamVect.get(0).gameScore+=handScorer.calculateHandScore(0);
            teamVect.get(1).gameScore+=handScorer.calculateHandScore(1);
            myUserInterface.printRoundOverSplash(teamVect);
            console.nextLine();
            resetBoard();
            dealToTeams();
        }
        endGame();

    }//end startGame

    //#####################################################
    void endGame()
    {
        myUserInterface.printGameOverSplash(teamVect);
        console.nextLine();
    }//end endGame


    //#######################################################
    boolean handOver()
    {
        if(teamVect.get(0).handMileage == 1000||teamVect.get(1).handMileage == 1000)
        return true;
        else 
        return false;
    }//end handOver

    //#######################################################
    boolean gameOver()
    {
        if((teamVect.get(0).gameScore >= 5000||teamVect.get(1).gameScore >= 5000)
           &&teamVect.get(0).gameScore!=teamVect.get(1).gameScore)
            //a team is over 5000 and it is not a tie
        return true;
        else
        return false;//if tie play another hand
    }//end gameOver

    //#####################################################
    int tryPlay( Card cardPlayed )
    {
        int otherTeam = (activeTeam+1)%(teamVect.size());
        boolean playValid = false;
              switch(cardPlayed.getTypeID())
        {
            case 1: playValid = getActiveTeam().checkValidDistance(25);
                    break;
            case 2: playValid = getActiveTeam().checkValidDistance(50);
                    break;
            case 3: playValid = getActiveTeam().checkValidDistance(75);
                    break;
            case 4: playValid = getActiveTeam().checkValidDistance(100);
                    break;
            case 5: playValid = getActiveTeam().checkValidDistance(200);
                    break;
                //card goes to distance pile
            case 6:   playValid = teamVect.get(otherTeam).checkValidHazard(cardPlayed.getTypeID());
            case 7:   playValid = teamVect.get(otherTeam).checkValidHazard(cardPlayed.getTypeID());
            case 8:   playValid = teamVect.get(otherTeam).checkValidHazard(cardPlayed.getTypeID());
            case 10:  playValid = teamVect.get(otherTeam).checkValidHazard(cardPlayed.getTypeID());
            // card goes on other team's battle pile
                     break;
            case 9:  playValid = teamVect.get(otherTeam).checkValidHazard(cardPlayed.getTypeID());
            //stop card goes on other team's speed pile
                     break;
            case 11: playValid = getActiveTeam().checkValidRemedy(cardPlayed.getTypeID());
            case 12: playValid = getActiveTeam().checkValidRemedy(cardPlayed.getTypeID());
            case 13: playValid = getActiveTeam().checkValidRemedy(cardPlayed.getTypeID());
            case 15: playValid = getActiveTeam().checkValidRemedy(cardPlayed.getTypeID());
            // card goes on own team's battle pile
                    break;
            case 14: playValid = getActiveTeam().checkValidRemedy(cardPlayed.getTypeID());
            // card goes on own team's speed pile
                     break;
            case 16:
            case 17:
            case 18:
            case 19: playValid = true;
                    break;
           

        }//end switch
       if(playValid)return 1;
       else return -1;
    }//end tryPlay

    //#####################################################
    void doPlay(Card cardPlayed)
    {
       int otherTeam = (activeTeam+1)%(teamVect.size());
        Table myTable = Table.getInstanceOf();
       // Boolean[] hazardStatus = myTable.getHazardStatus(otherTeam);

        switch( cardPlayed.getTypeID() )
        {
            //if played on active team's pile,
            //then default and playOnPile determines where to play it
            case 6:
            case 7:
            case 8:
            case 10: // card goes on other team's battle pile
                myTable.playOnPile(otherTeam, cardPlayed);
                teamVect.get(otherTeam).playOnPile(cardPlayed);//changes hazards
                     break;
            case 9: // card goes on other team's speed pile
                myTable.playOnPile(otherTeam, cardPlayed);
                teamVect.get(otherTeam).playOnPile(cardPlayed);//changes hazards
                
                //hazardStatus[1]=true;//set speedLimit true
               // myTable.setHazardStatus(otherTeam, hazardStatus);
                     break;
            default:
                myTable.playOnPile(activeTeam, cardPlayed);
                getActiveTeam().playOnPile(cardPlayed);//changes hazards
                     break;
        }//end switch

    }//end doPlay


    //#####################################################
    char promptUser(String question)
    {
        myUserInterface.askUser(question);
        display();
        int activePlayer = teamVect.get(activeTeam).activePlayer;
        char answer = teamVect.get(activeTeam).playerVect.get(activePlayer).executeTurn();
        myUserInterface.clearQuestion();
        return answer;
    }//end promptUser


    //#####################################################
    void informUser(String question)
    {
        myUserInterface.askUser(question);
        display();
        myUserInterface.clearQuestion();
        console.nextLine();//waits for user to press enter
        
    }//end promptUser


    //#####################################################
    Card drawCard()
    {
        Card topCard = mainDeck.drawCard();
        if (topCard==null)
        {
            //set delayed action flag so we give bonus points to winning team
        }//end if

        return topCard;
    }//end promptUser

    //#####################################################
    void startTurn()
    {
        //draw a card
        Card topCard = drawCard();
        handScorer.checkDelayedAction();
        Character tempChar;
        Integer tempInt;
        int playable =0;
        boolean safteyPlayed = false;
        boolean discarding = false;
              //check for empty deck
        if(topCard!=null)
        {
            getActiveTeam().giveCard(topCard);
        }//end if
        
        boolean turnOver=false;


        while(!turnOver)
        {
            safteyPlayed = false;
            discarding = false;
        if(teamVect.get(activeTeam).playerVect.get(teamVect.get(activeTeam).activePlayer).humanControlled)
        {//we have a human player so prompt
            tempChar = promptUser("It's your turn! Which card would you like to play?(1-7, d to discard.): ");
            if(tempChar == 'd'|| tempChar == 'D')
            {
                tempChar = promptUser("Which card would you like to discard? (1-7): ");
                tempInt = Integer.parseInt(tempChar.toString());
                discarding = true;//set flag for discard
            }//end discard prompt
            else
            {
            tempInt = Integer.parseInt(tempChar.toString());
            playable = tryPlay(getActiveTeam().getActivePlayer().getHand().getCard(tempInt-1));
            }//end not discarding
        }//end if human player
        else
        {
            tempChar = promptUser("It is the computer player's turn. Press enter to continue...");
            tempInt = Integer.parseInt(tempChar.toString());
            if(tempInt==9)
            {
                playable = -2;//computer discarding
            }//computer
            else playable = 1;
           // console.nextLine();
        }//end comp player
        
         //get played card subtype                    

        //will  always be 1 for computer player
         if(playable==1 || discarding)
         {
            int tempID = getActiveTeam().getActivePlayer().getHand().getCard(tempInt-1).getTypeID();
             if(tempID > 15 && !discarding)
             {//only play safety if not discarding
                safteyPlayed = true;
             }//safetycard played

            String tempString = getActiveTeam().getActivePlayer().getHand().getCard(tempInt-1).toStringRep().get(1);
            String tempString2 = getActiveTeam().getActivePlayer().getHand().getCard(tempInt-1).toStringRep().get(2);

                if(!discarding)//play card on piles and inform the user of the play
               {
                    doPlay(getActiveTeam().getActivePlayer().playCard(tempInt));
                    informUser(getActiveTeam().getActivePlayer().name+" has played "+ tempString +" "
                        +tempString2+ "...Press enter to continue...");
                }//end if
               else//just remove from hand
                {
                    getActiveTeam().getActivePlayer().playCard(tempInt);//removes card from hand
                    informUser(getActiveTeam().getActivePlayer().name+" has discarded "+ tempString +" "
                        +tempString2+ "...Press enter to continue...");
                }//end else
             

             turnOver=true;
             if(safteyPlayed)
             {
                turnOver=false;
                topCard = drawCard();//give extra card for extra turn
                handScorer.checkDelayedAction();
                if(topCard!=null)
                {
                getActiveTeam().giveCard(topCard);
                }//end if

             }//end if safetyplayed             

         }//end if

         else if(playable == -1)
         {
             tempChar = promptUser("Sorry, not a valid play. Would you like to discard instead?(y/n):  ");
             if(tempChar=='y')
             {
                getActiveTeam().getActivePlayer().playCard(tempInt);//removes card from hand
                turnOver = true;
             }//end if

         }//end else

        else 
         {//computer is discarding
                String tempString = getActiveTeam().getActivePlayer().getHand().getCard(1).toStringRep().get(1);
                String tempString2 = getActiveTeam().getActivePlayer().getHand().getCard(1).toStringRep().get(2);
                informUser(getActiveTeam().getActivePlayer().name+" has discarded "+ tempString +" "
                        +tempString2+ "...Press enter to continue...");
                getActiveTeam().getActivePlayer().playCard(1);//removes first card from hand
                turnOver = true;
         }//end else

        }//end while

        turnCompleted();
    }//end startturn

    //#####################################################
    void turnCompleted()
    {
        //toggle player and team
        teamVect.get(activeTeam).toggleActivePlayer();
        activeTeam = (activeTeam+1)%2;
    }//end promptUser

    //################################################
    void dealToTeams()
    {
        Vector<Card> tempVector = new Vector<Card>(12);
        for( int i = 0 ; i < 2 ; i++)
        {
            for( int j = 0 ; j < 12 ; j++)
            {
                tempVector.add(mainDeck.drawCard());
            }
            teamVect.elementAt(i).giveHands(tempVector);
            tempVector.clear();
        }
    }

    //##############################################
    void display()
    {
        myUserInterface.display(activeTeam, teamVect);
    }

        //##############################################
    void resetBoard()
    {
        Table myTable = Table.getInstanceOf();
        mainDeck.shuffleDeck();
        myTable.teamPiles[0].get(0).clearPile();
        myTable.teamPiles[0].get(1).clearPile();
        myTable.teamPiles[1].get(0).clearPile();
        myTable.teamPiles[1].get(1).clearPile();
        teamVect.get(0).resetTeam();
        teamVect.get(1).resetTeam();
        handScorer.resetScoreKeeper();
    }//resetBoard


    //##############################################
    public static void main( String args[] )
    {//I copied this to the millebornes.main method in compliance with
        //the requirements

        Controller myController = new Controller();
        myController.dealToTeams();

        //System.out.println(myController.getTeam(0).toString() + "\n" +
        //                   myController.getTeam(1).toString() );

        myController.display();

    } // end testMain

}//end class Controller
